package com.songlanyun.modules.refillorder.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.enums.BillConstant;
import com.songlanyun.common.enums.OrderConstant;
import com.songlanyun.common.enums.PayConstant;
import com.songlanyun.common.enums.RefillOrderConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.*;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.modules.account.model.vo.AccountVO;
import com.songlanyun.modules.account.service.AccountService;
import com.songlanyun.modules.account.service.UserIdentityAssetService;
import com.songlanyun.modules.account.service.UserThirdIdentityService;
import com.songlanyun.modules.memberbill.service.SaleRefillCardBillService;
import com.songlanyun.modules.exception.OrderException;
import com.songlanyun.modules.payorder.entity.PayOrder;
import com.songlanyun.modules.payorder.service.PayOrderService;
import com.songlanyun.modules.rabbitmq.DelayedConstant;
import com.songlanyun.modules.rabbitmq.service.SendMsgService;
import com.songlanyun.modules.refillcard.entity.SaleRefillCardEntity;
import com.songlanyun.modules.refillcard.service.SaleRefillCardService;
import com.songlanyun.modules.refillorder.model.RefillCardOrderDTO;
import com.songlanyun.modules.refillorder.model.RefillCardOrderVO;
import com.songlanyun.modules.refillorder.model.RefillOrderPayVo;
import com.songlanyun.modules.sysbill.service.SysBillService;
import com.songlanyun.modules.usercard.entity.UserCardEntity;
import com.songlanyun.modules.usercard.service.UserCardService;
import com.songlanyun.pay.common.api.ApiResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.songlanyun.modules.refillorder.dao.SaleRefillCardOrderDao;
import com.songlanyun.modules.refillorder.entity.SaleRefillCardOrderEntity;
import com.songlanyun.modules.refillorder.service.SaleRefillCardOrderService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("yxtSaleRefillCardOrderService")
public class SaleRefillCardOrderServiceImpl extends ServiceImpl<SaleRefillCardOrderDao, SaleRefillCardOrderEntity> implements SaleRefillCardOrderService {


    @Resource
    private SaleRefillCardService saleRefillCardService;

    @Resource
    private UserIdentityAssetService userIdentityAssetService;

    @Resource
    private SaleRefillCardBillService saleRefillCardBillService;

    @Resource
    private UserThirdIdentityService userThirdIdentityService;

    @Resource
    private PayOrderService payOrderService;

    @Resource
    private SysBillService sysBillService;

    @Resource
    private AccountService accountService;

    @Resource
    private SendMsgService sendMsgService;

    @Resource
    private UserCardService userCardService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Date startTime = MapUtil.getDate(params, "start_time");
        if(ObjectUtil.isNotNull(startTime))
        {
            params.put("st",startTime.getTime());
        }

        Date endTime = MapUtil.getDate(params, "end_time");
        if(ObjectUtil.isNotNull(endTime))
        {
            endTime = DateUtils.addDateDays(endTime,1);
            params.put("et",endTime.getTime());
        }

        IPage<SaleRefillCardOrderEntity> page = this.baseMapper.queryRefillCardOrderPage(new Query<SaleRefillCardOrderEntity>().getPage(params), params);
        return new PageUtils(page);
    }

    /**
     * 购买充值卡
     *
     * @param
     */
    @Override
    @Transactional
    public RefillOrderPayVo buy(RefillCardOrderDTO dto) {

        //查询该充值卡信息
        Long refillCardId = dto.getRefillCardId();
        SaleRefillCardEntity card = saleRefillCardService.getByIdAndUp(refillCardId);

        //初始化支付订单
        PayOrder payOrder = payOrderService.initPayOrder(dto.getUserId(), card.getMoney(),
                OrderConstant.PayMode.getByCode(dto.getPayMode()), OrderConstant.OrderType.REFILL_ORDER);
        //生成充值订单
        createByCard(dto, card, payOrder);
        ApiResult apiResult = null;
        //判断支付方式
        if (dto.getPayMode().equals(OrderConstant.PayMode.WE_CHAT.getCode())) {
            // 发起微信支付
            // 生成支付信息给前台，供其唤起相应的支付
            //微信的分程序已做了转换，此次不用管//"openid如果是公众号或小程序需要设置否则不用管"//微信小程序支付
            if (("applet").equals(dto.getClient())) {
                // 获取会员的openid，发起支付
                String openId = userThirdIdentityService.getOpenIdByUserId(dto.getUserId(), true);
                apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), openId, PayConstant.PayType.WECHAT_TRADE_APPLET_PAY.getCode());
            }else {
                //微信app支付
                apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), "", PayConstant.PayType.WECHAT_TRADE_APP_PAY.getCode());
            }


        } else {
            apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), "", PayConstant.PayType.ALIPAY_TRADE_APP_PAY.getCode());
        }

        return new RefillOrderPayVo(payOrder, apiResult);

    }

    /**
     * 直接充值
     *
     * @param
     */
    @Transactional
    @Override
    public RefillOrderPayVo directBuy(RefillCardOrderDTO dto) {


        //初始化支付订单
        PayOrder payOrder = payOrderService.initPayOrder(dto.getUserId(), dto.getMoney(),
                OrderConstant.PayMode.getByCode(dto.getPayMode()), OrderConstant.OrderType.REFILL_ORDER);
        //生成充值订单
        createByCard(dto, payOrder);
        ApiResult apiResult = null;
        //判断支付方式
        if (dto.getPayMode().equals(OrderConstant.PayMode.WE_CHAT.getCode())) {
            // 发起微信支付
            // 生成支付信息给前台，供其唤起相应的支付
            //微信的分程序已做了转换，此次不用管//"openid如果是公众号或小程序需要设置否则不用管"//微信小程序支付
            if (("applet").equals(dto.getClient())) {
                // 获取会员的openid，发起支付
                String openId = userThirdIdentityService.getOpenIdByUserId(dto.getUserId(), true);
                apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), openId, PayConstant.PayType.WECHAT_TRADE_APPLET_PAY.getCode(),"转入");
            }else {
                //微信app支付
                apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), "", PayConstant.PayType.WECHAT_TRADE_APP_PAY.getCode(),"转入");
            }
        } else if(dto.getPayMode().equals(OrderConstant.PayMode.ALIPAY_HUIFU.getCode())) {
            apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), "余额转入","余额转入", PayConstant.PayType.ORDER_PAY_TYPE_ALIPAY_HUIFU_APP.getCode(), "转入");
        }else if (dto.getPayMode().equals(OrderConstant.PayMode.ALIPAY_HSQ.getCode())) {
            apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), PayConstant.PayType.ORDER_PAY_TYPE_ALIPAY_HSQ_MAIN.getCode(), "转入", dto.getLongitude(), dto.getLatitude());

        }else if (dto.getPayMode().equals(OrderConstant.PayMode.KJ.getCode())) {
            UserCardEntity userCardEntity = userCardService.loadById(dto.getCardId(), true);
            apiResult = payOrderService.pay(payOrder.getCode(),userCardEntity.getTokenNo(), payOrder.getTotalAmount().toString(), "余额转入","余额转入", PayConstant.PayType.ORDER_PAY_TYPE_ADAPAY_KJ_APP.getCode(), "转入");        }
        else
        {
            apiResult = payOrderService.pay(payOrder.getCode(), payOrder.getTotalAmount().toString(), "", PayConstant.PayType.ALIPAY_TRADE_APP_PAY.getCode(),"转入");
        }


        return new RefillOrderPayVo(payOrder, apiResult);
    }


    /**
     * 成功支付后调用,所有安全校验必须之前处理完成才可以调用，来处理充值成功后的事情
     * <p>
     * 1通过payOrder找到对应的SaleRefillCardOrderEntity,去改变它的状态;
     * 2完成充值
     * 3记录账单明细
     *
     * @param payOrder
     * @return
     */
    @Override
    public PayOrder paymentHandle(PayOrder payOrder) {
        if (payOrder.getPaymentStatus().equals(OrderConstant.PaymentStatus.SUCCESS)) {

            //1 通过payOrder找到对应的SaleRefillCardOrderEntity,去改变它的状态;
            String outTradeNo = payOrder.getCode();//交易订单编号
            //查询充值订单记录
            SaleRefillCardOrderEntity order = baseMapper.selectOne(
                    new LambdaQueryWrapper<SaleRefillCardOrderEntity>()
                            .eq(SaleRefillCardOrderEntity::getPayOrderCode, outTradeNo)
            );

            order.setPaymentStatus(RefillOrderConstant.PaymentStatus.SUCCESS);//支付成功
            order.setTransactionStatus(RefillOrderConstant.TransactionStatus.CLOSE);//交易结束
            order.setTradeNo(payOrder.getThirdPayCode());//交易流水号（第三方）
            order.setPayMode(payOrder.getPayMode());//支付方式
            order.setPayTime(System.currentTimeMillis());//支付时间
            order.setCloseStatus(RefillOrderConstant.CloseStatus.NOT_CLOSE);
            baseMapper.updateById(order);

            //2 完成充值
            //3 记录账单明细  更新会员余额 并生成充值订单账单明细
            //余额增加的金额   所需费用+赠送额度
            BigDecimal addMoney = order.getRefillCardMoney().add(order.getRefillCardAppend());
            saleRefillCardBillService.addBalance(order.getUserId(), addMoney, outTradeNo, BillConstant.InnerMode.RECHARGE);

            //4、充值成功记录平台账单
            String mobile = accountService.getMobileByUserId(order.getUserId());//会员手机号
            //入账入的是支付的金额
            sysBillService.saveIncomeBill(payOrder.getPayMode(), BillConstant.BillType.BALANCE_RECHARGE, order.getRefillCardMoney(),
                    outTradeNo, payOrder.getThirdPayCode(), mobile);
        }

        return payOrder;
    }

    /**
     * 关闭充值订单
     *
     * @param id
     */
    @Override
    public void closeOrder(Long id) {
        PayOrder payOrder = payOrderService.getById(id);
        payOrderService.verifyCloseOrder(payOrder);

        //将订单修改为超时关闭
        payOrder.setCloseMode(OrderConstant.CloseMode.PAY_EXPIRE);
        payOrder.setCloseTime(System.currentTimeMillis());
        payOrder.setClose(true);
        payOrder.setPaymentStatus(OrderConstant.PaymentStatus.EXPIRE);
        payOrderService.updateById(payOrder);

        SaleRefillCardOrderEntity entity = this.getByPayOrderCode(payOrder.getCode(), false);
        if (entity != null) {
            entity.setCloseStatus(RefillOrderConstant.CloseStatus.PAY_CLOSE);
            entity.setTransactionStatus(RefillOrderConstant.TransactionStatus.CLOSE);
            this.updateById(entity);

        }
    }

    /**
     * 根据聚合订单号查询充值订单
     *
     * @param code
     * @param isThrow
     * @return
     */
    @Override
    public SaleRefillCardOrderEntity getByPayOrderCode(String code, boolean isThrow) {
        SaleRefillCardOrderEntity one = this.getOne(
                new LambdaQueryWrapper<SaleRefillCardOrderEntity>()
                        .eq(SaleRefillCardOrderEntity::getPayOrderCode, code)
                        .last("limit 1")
        );
        if (one == null) {
            if (isThrow) {
                throw new RRException(OrderException.ORDER_NOT_EXISTS);
            }
        }

        return one;
    }

    @Override
    public List<RefillCardOrderVO> exportList(Map<String, Object> params) {
        return this.baseMapper.exportList(params);
    }



    /**
     * 根据充值卡生成充值卡订单
     *
     * @param dto
     * @param card
     */
    private void createByCard(RefillCardOrderDTO dto, SaleRefillCardEntity card, PayOrder payOrder) {
        SaleRefillCardOrderEntity order = new SaleRefillCardOrderEntity();
        order.setUserId(dto.getUserId());//会员id
        order.setRefillCardId(dto.getRefillCardId());//充值卡
        order.setPayMode(OrderConstant.PayMode.getByCode(dto.getPayMode()));//支付方式

        order.setCreateTimeMillis(payOrder.getCreateTimeMillis());//当前时间戳
        //赋值
        order.setRefillCardName(card.getName());//卡名
        order.setRefillCardMoney(card.getMoney());//充值卡所需钱数
        order.setRefillCardAppend(card.getAppend());//额外的送多少
        setStatus(
                order,
                RefillOrderConstant.PaymentStatus.NO_PAY,//未支付
                RefillOrderConstant.CloseStatus.NOT_CLOSE,//未关闭
                RefillOrderConstant.TransactionStatus.WAIT_PAYMENT//已下单,待支付
        );

        order.setExpirationTime(payOrder.getExpiredPayTime());//过期时间
        order.setCode("C" + OrderGen.generateOrderNo());//充值订单编号

        //TODO 目前实际支付与所需钱数一样，以后可能会有打折情况
        order.setFactCost(card.getMoney());//实际支付

        order.setPayOrderId(payOrder.getId());//聚合支付订单id
        order.setPayOrderCode(payOrder.getCode());//聚合支付订单编号

        //生成订单
        baseMapper.insert(order);
    }


    /**
     * 根据充值卡生成充值卡订单
     *
     * @param dto
     * @param payOrder
     */
    private void createByCard(RefillCardOrderDTO dto, PayOrder payOrder) {
        SaleRefillCardOrderEntity order = new SaleRefillCardOrderEntity();
        order.setUserId(dto.getUserId());//会员id
        order.setRefillCardId(0L);//充值卡
        order.setPayMode(OrderConstant.PayMode.getByCode(dto.getPayMode()));//支付方式

        order.setCreateTimeMillis(payOrder.getCreateTimeMillis());//当前时间戳
        //赋值
        order.setRefillCardName("直接转入");//卡名
        order.setRefillCardMoney(dto.getMoney());//充值卡所需钱数
        order.setRefillCardAppend(BigDecimal.ZERO);//额外的送多少
        setStatus(
                order,
                RefillOrderConstant.PaymentStatus.NO_PAY,//未支付
                RefillOrderConstant.CloseStatus.NOT_CLOSE,//未关闭
                RefillOrderConstant.TransactionStatus.WAIT_PAYMENT//已下单,待支付
        );

        order.setExpirationTime(payOrder.getExpiredPayTime());//过期时间
        order.setCode("C" + OrderGen.generateOrderNo());//充值订单编号
        order.setFactCost(dto.getMoney());//实际支付

        order.setPayOrderId(payOrder.getId());//聚合支付订单id
        order.setPayOrderCode(payOrder.getCode());//聚合支付订单编号

        //生成订单
        baseMapper.insert(order);
    }



    /**
     * 设置状态
     * paymentStatus    支付状态
     * closeStatus  关闭状态
     * transactionStatus    交易状态
     */
    public void setStatus(SaleRefillCardOrderEntity order,
                          RefillOrderConstant.PaymentStatus paymentStatus,
                          RefillOrderConstant.CloseStatus closeStatus,
                          RefillOrderConstant.TransactionStatus transactionStatus) {
        order.setPaymentStatus(paymentStatus);
        order.setCloseStatus(closeStatus);
        order.setTransactionStatus(transactionStatus);

    }


}
